package com.navy.chen.tetrisgame.thread;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;
import android.view.SurfaceHolder;

import com.navy.chen.tetrisgame.bean.Tetris;
import com.navy.chen.tetrisgame.dao.TetrisDao;
import com.navy.chen.tetrisgame.interfaces.GameControlListenr;
import com.navy.chen.tetrisgame.interfaces.ProductListener;
import com.navy.chen.tetrisgame.interfaces.UiListener;
import com.navy.chen.tetrisgame.tool.Config;
import com.navy.chen.tetrisgame.tool.DrawHelper;
import com.navy.chen.tetrisgame.tool.Tools;

import java.util.List;

/**
 * Created by Administrator on 2017/12/2.
 * 画画和游戏的控制
 */
public class GameThread extends Thread implements GameControlListenr {

    private final String TAG = Config.TAG + getClass().getSimpleName();
    private SurfaceHolder holder;
    public boolean isRunning = true;

    private Tetris curTetris;
    private Tetris lastTetris;


    private Canvas tempCanvas;
    private Bitmap bitmap;
    private int moveDirection = 0;
    private boolean isDraw = false;

    private int scores = 0;
    private int level = 1;
    private int startSpeed = 460 + (level * 40);
    private int speed = startSpeed;
    private int maxMoveStep = 2;//左移动或者右移动一次性最多移动两个位置
    private int rotateDiretion = 0;

    private ProductListener productListener;
    private UiListener uiListener;
    private GameControlListenr gameControlListenr;

    public boolean isPause = false;

    private TetrisDao tetrisDao;

    public GameThread(SurfaceHolder holder) {
        this.holder = holder;
        gameControlListenr = this;
        tetrisDao = new TetrisDao();
    }


    @Override
    public synchronized void run() {
        Log.d(TAG, "线程开始");
        tempCanvas = new Canvas(bitmap);
        initBg();

        curTetris = Tetris.randomTetris();
        initLastTetris();

        while (isRunning) {
            if (isPause) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if (!isDraw) {//没有画就可以移动旋转
                if (rotateDiretion % 4 > 0) {
                    int rotateTime = rotateDiretion % 4;
                    for (int i = 0; i < rotateTime; i++) {
                        if (tetrisDao.rotate(curTetris, Tetris.RIGHT)){
                            drawTetris();
                            sleepM(40);
                        }else {
                            break;
                        }
                    }
                    rotateDiretion = 0;
                }
                if (moveDirection != 0){//
                    int diretion = moveDirection>0 ? Tetris.RIGHT:Tetris.LEFT;
                    if (Math.abs(moveDirection)>=maxMoveStep){
                        moveDirection = diretion * maxMoveStep;
                    }
                    for (int i=1; i<=Math.abs(moveDirection); i++){
                        if (tetrisDao.move(curTetris, diretion)){
                            drawTetris();
                            sleepM(40);
                        }else {
                            break;
                        }
                    }
                }
                moveDirection = 0;
            }
            if (tetrisDao.down(curTetris)) {
                //curTetris.setY(Config.getInstance().getSideLength() + curTetris.getY());
                Log.d(TAG, "能移动。。。。");
                drawTetris();
                sleepM();
                isDraw = false;

            } else {

                Tetris tetris = (Tetris) curTetris.clone();
                Tools.print(tetris.getMatrix());
                Log.d(TAG, String.format("tetris y=%f", tetris.getY() / Config.getInstance().getSideLength()));
                Log.d(TAG, String.format("tetris x=%f", tetris.getX()/Config.getInstance().getSideLength()));
                DrawHelper.getInstance().drawATetris(tetris, tempCanvas, Config.getInstance().getSideLength());
                postCanvas();

                //判断是否可以得分， 并消除得分行
                List<Integer> lines = tetrisDao.getFillTetrisLines(tetris);
                if (lines.size() != 0) {

                    //消去该行  由于俄罗斯方块消去的行都是连起
                    int startLine = lines.get(0);
                    int endLine = lines.get(lines.size() - 1);
                    float sideLength = Config.getInstance().getSideLength();
                    float width = sideLength * Config.getInstance().width_num;
                    clearTetrisLines(startLine, endLine, sideLength, width);

                    scores += Math.pow(2, lines.size() - 1);
                    uiListener.onGameScoresChange(scores);
                    if (scores / 1000 > level) {
                        level = scores / 1000 + 1;
                        speed = startSpeed;
                        uiListener.onGameLevelChange(level);
                    }
                } else {
                    if (tetrisDao.isGameOver()){
                        isRunning = false;
                        uiListener.onGameFinsih(scores);
                    }
                }

                isDraw = true;
                speed = startSpeed;
                curTetris = productListener.productTetris();
                curTetris.setX(Tetris.getStartX(curTetris.getMatrix()[0].length));
                curTetris.setY(0);
                initLastTetris();
            }
        }

    }



    public void drawTetris() {
        DrawHelper.getInstance().drawATetris(lastTetris, tempCanvas, Config.getInstance().getSideLength());
        DrawHelper.getInstance().drawATetris(curTetris, tempCanvas, Config.getInstance().getSideLength());
        initLastTetris();
        postCanvas();
    }




    public void setUiListener(UiListener uiListener) {
        this.uiListener = uiListener;
    }

    public void setProductListener(ProductListener productListener) {
        this.productListener = productListener;
    }

    public GameControlListenr getGameControlListenr() {
        return gameControlListenr;
    }


    @Override
    public void speedUp() {
        if (speed >= 100) {
            speed -= 100;
        }
    }

    @Override
    public void rotate() {
        rotateDiretion++;
    }

    @Override
    public void pauseGame() {
        isPause = true;
    }

    @Override
    public synchronized void playGame() {
        isPause = false;
        notify();
    }

    @Override
    public  void move(int diretion) {
        moveDirection += diretion;
        if (Math.abs(moveDirection)>=maxMoveStep){
            moveDirection = diretion * maxMoveStep;
        }
    }

    @Override
    public void newGame(){

    }

    public void setBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
    }



    private void initBg() {
        DrawHelper.getInstance().drawBg(tempCanvas, Config.getInstance().getTetrisContentColor(),
                Config.getInstance().width_num, Config.getInstance().heght_num, Config.getInstance().getSideLength());
        postCanvas();
        Log.d(TAG, "背景初始化成功");
    }

    private void postCanvas() {
        Canvas canvas = holder.lockCanvas();
        if (canvas == null) {
            Log.d(TAG, "postCanvas canvas ==null");
        } else {
            canvas.drawBitmap(bitmap, 0, 0, null);
            holder.unlockCanvasAndPost(canvas);
        }
    }

    private void clearTetrisLines(int startLine, int endLine, float sideLength, float width){
        /**
         * 1 数组下移
         * 2 清除消去的行的图片
         * 3 画背景
         * 4.通知ui
         */
        Tools.moveDownMatrixContent(tetrisDao.getContainer(), startLine, endLine);
        RectF clearRectangle = new RectF(0, startLine * sideLength,
                width, (endLine + 1) * sideLength);
        DrawHelper.getInstance().clearRectangle(tempCanvas, bitmap, clearRectangle);
        postCanvas();
    }

    private void initLastTetris() {
        lastTetris = (Tetris) curTetris.clone();
        lastTetris.setColor(Config.getInstance().getTetrisContentColor());
    }
    private void sleepM() {
        try {
            sleep(speed);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    private void sleepM(int millis) {
        try {
            sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
